﻿// Learn more about F# at http://fsharp.net

module EmitType
open System.Reflection.Emit

let a = DynamicMethod("pippo", typeof<int>,[||])
let il = a.GetILGenerator()

type T_symbol = 
  {
    mutable IsUsed  : bool
    mutable Id      : int
    IsArg   : bool
  }
  member this.Name with get () = sprintf "T%d" this.Id
  static member Null =
    { IsUsed = true; Id = -1; IsArg = false }
  static member Zero =
    { IsUsed = true; Id = -2; IsArg = false }
  static member This =
    { IsUsed = true; Id = 0; IsArg = true }
//il.Emit(


type Id = int
//
//type Emit = 
//  | Assign of Var * Expr
//  | Label of Label
//  | Jump of Label
//  | TJump of bool * Label
//  | FJump of bool * Label
//
//and T = Expr * Var
//
//and Label = string
//
//and Expr = 
//  | Op of OpCodes
type Emit =
  | Expr of EmitExpr * T_symbol
  | Stmt of EmitStmt
  | Label of EmitLabel
  | Jmp of EmitJmp
  | Comment of string

and EmitExpr =
  | Add of T_symbol * T_symbol
  | Sub of T_symbol * T_symbol
  | Div of T_symbol * T_symbol
  | Mul of T_symbol * T_symbol
  | Mod of T_symbol * T_symbol
  | And of T_symbol * T_symbol
  | Or of T_symbol * T_symbol
  | Not of T_symbol
  | Eq of T_symbol * T_symbol
  | Neq of T_symbol * T_symbol
  | Geq of T_symbol * T_symbol
  | Leq of T_symbol * T_symbol
  | Gt of T_symbol * T_symbol
  | Lt of T_symbol * T_symbol  
  | Neg of T_symbol  
  | ReadArray of T_symbol * T_symbol
  | GetField of T_symbol * Id
  | DirectCall of string * T_symbol list
  | Call of Id * T_symbol list  
  | Int of int
  | Str of string
  | Bool of bool
  | Id of T_symbol
  | Length of T_symbol
  | New of string
  | NewArray of Ast.Type * T_symbol
  | This
  | Null


and EmitStmt =
  | Assign of T_symbol * T_symbol
  | SetArray of T_symbol * T_symbol * T_symbol
  | SetField of T_symbol * Id * T_symbol
  | Return of T_symbol
  | ReturnVoid

and EmitLabel = string ref

and EmitJmp =
  | Tjmp of T_symbol * EmitLabel
  | Fjmp of T_symbol * EmitLabel
  | Jmp of EmitLabel

let NULL_POINTER : EmitLabel = ref "NULL_POINTER"
let ARRAY_OUT_OF_BOUNDS : EmitLabel = ref "ARRAY_OUT_OF_BOUNDS"
  

type ClassName = string
type ClassFields = string list
type ClassMethods = (string * T_symbol list * T_symbol list * Emit list) list